#pragma once
#include"Common.h"

//定长内存池
template<class T>
class ObjectPool {
public:
	T* New()
	{
		T* obj = nullptr;
		//如果有还回的内存，直接使用还回的内存块
		if (_freeList)
		{
			obj = (T*)_freeList;
			_freeList = NextObj(_freeList);//内存块中首个指针大小（头4/8字节）存的是下一个还回内存块的地址
		}
		else
		{
			//如果内存块为空或者剩余的内存块不足以继续申请T对象
			if (_remainbytes < sizeof(T))
			{
				_remainbytes = 128 * 1024;//128kb
				_memory = (char*)SystemAlloc(_remainbytes>>PAGE_SHIFT);
				if (_memory == nullptr)
				{
					throw std::bad_alloc();
				}
			}
			obj = (T*)_memory;
			size_t objsize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
			_memory += objsize;
			_remainbytes -= objsize;
		}
		//使用定位new调用对象的构造函数创建对象，不会自动分配内存
		new(obj)T;
		return obj;
	}

	void Delete(T* obj)
	{
		//因为定位new不会管理内存释放，必须显示调用对象的析构函数
		obj->~T();
		//头插到freeList
		*(void**)obj = _freeList;
		_freeList = obj;
	}
private:
	char* _memory = nullptr;//指向内存块的指针
	void* _freeList = nullptr;//管理还回内存的自由链表 
	size_t _remainbytes = 0;//内存块中剩余的字节数
};

